"""
    Python的魔术方法协议体系：

是语言层面的行为约定，类似网络通信协议

比C++操作符重载更规范但灵活性稍低

体现了Python"约定优于配置"的设计哲学

通过鸭子类型实现多态，无需显式继承

使得自定义类能无缝融入Python生态系统

这种设计既保证了语言的简洁性，又提供了足够的扩展能力，是Python"大道至简"哲学的重要体现。
理解这一点，就能更好地编写Pythonic的代码，让自定义对象如原生类型般自然工作。
"""

#对象周期方法
class Phone:
    def __new__(cls, brand):
        print(f'正在创建{brand}手机！')
        return super().__new__(cls) #在类的对象被创建前，使用super方法调用object类的__new__创建该实例对象

    def __init__(self, brand):
        print(f'正在初始化{brand}手机！')
        self.brand = brand
    
    def __del__(self):
        print(f'{self.brand}手机被回收')

phone = Phone('华为')
del phone

#对象表示法
class Contact:
    def __init__(self, name, phone):
        self.name = name
        self.phone = phone
    
    def __str__(self):
        return f'联系人{self.name}'
    
    def __repr__(self):
        return f'联系人{self.name}, 电话号码：{self.phone}'
    
    def __format__(self, format_spec):
        return '联系人{0}, 电话号码：{1}'.format(self.name, self.phone)
    
alice = Contact("Alice", "13800138000")
print(alice)
print(repr(alice))
print(format(alice, ''))
#观察一下这些魔术方法是怎么被‘触发’的？
#调用这些魔术方法，就好像遵循某些协议，使用特殊格式语法才能调用他们，我称之为--触发条件

#数值运算方法
class Vector():
    def __init__(self, x, y):
        self.x = x
        self.y = y
    
    def __add__(self, orther):
        return Vector(self.x + orther.x, self.y + orther.y)
    
    def __eq__(self, orther):
        return self.x == orther.y and self.y == orther.y
    
    def __str__(self):
        return f'vector({self.x}, {self.y})'
v1 = Vector(1, 3)
v2 = Vector(2, 4)

print('v1 + v2:', v1 + v2)
print('v1 == v2:', v1 == v2)
print('v1: ',  v1)

#容器类型方法
class Playlist:
    def __init__(self, song):
        self.songs = list(song)
    
    def __len__(self):
        return len(self.songs)
    
    def __getitem__(self, index):
        return self.songs[index]
    
    def __setitem__(self, key, value):
        if key < len(self.songs):
            self.songs[key] = value
        else:
            # 当索引超出范围时，使用 append 方法添加元素
            self.songs.append(value)
    
    def __contains__(self, song):
        return song in self.songs
    
    def __iter__(self):
        return iter(self.songs)

my_playlist = Playlist(["Song1", "Song2", "Song3"])
print(len(my_playlist))
print(my_playlist[1])
print('Song2' in my_playlist)
my_playlist[3] = 'Song4'
for song in my_playlist:
    print(song)